package com.ipmirror.servlets;

import com.icesoft.faces.webapp.xmlhttp.PersistentFacesServlet;
import com.ipmirror.navigation.NavigationBean;
import com.ipmirror.navigation.NavigationEnum;
import org.apache.log4j.Logger;

import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class PersistentFacesServletWrapper extends PersistentFacesServlet {
	private static final Logger LOG = Logger.getLogger(PersistentFacesServletWrapper.class);

	private static final String ERROR_PAGE = "serverErrorPage";
	private String serverErrorPage;

	public void init(ServletConfig servletConfig) throws ServletException {
		super.init(servletConfig);
		serverErrorPage = servletConfig.getInitParameter(ERROR_PAGE);
	}

	public void service(ServletRequest request, ServletResponse response)
			throws ServletException, IOException {
		try {
			super.service(request, response);
		} catch (Throwable e) {
			e.printStackTrace();
			redirectToServerErrorPage((HttpServletRequest) request,
					(HttpServletResponse) response);
		}
	}

	private void redirectToServerErrorPage(HttpServletRequest request,
			HttpServletResponse response) throws IOException {
		boolean toRedirectToErrorPage = false;
		try {
			NavigationBean nav = (NavigationBean) getManagedBean("navigation",
					getFacesContext(request, response));
			
			if (nav != null &&  !nav.getLastPageKey().equals(NavigationEnum.DEFAULT_EXCEPTION.getMenuId())) {
				nav.navigationExceptionListener();
				toRedirectToErrorPage = true;
			}

			if (!serverErrorPage.equals("")  && toRedirectToErrorPage) {
				response.sendRedirect(request.getContextPath() + serverErrorPage);
			}
		} catch (Exception e) {
		//	e.printStackTrace();
		}

	}

	protected FacesContext getFacesContext(HttpServletRequest request,
			HttpServletResponse response) {
		FacesContext facesContext = FacesContext.getCurrentInstance();
		if (facesContext == null) {

			FacesContextFactory contextFactory = (FacesContextFactory) FactoryFinder
					.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
			LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
					.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
			Lifecycle lifecycle = lifecycleFactory
					.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);

			facesContext = contextFactory.getFacesContext(request.getSession()
					.getServletContext(), request, response, lifecycle);

			// Set using our inner class
			InnerFacesContext.setFacesContextAsCurrentInstance(facesContext);

			// set a new viewRoot, otherwise context.getViewRoot returns null
			UIViewRoot view = facesContext.getApplication().getViewHandler()
					.createView(facesContext, "");
			facesContext.setViewRoot(view);
		}
		return facesContext;
	}

	// You need an inner class to be able to call
	// FacesContext.setCurrentInstance
	// since it's a protected method
	private abstract static class InnerFacesContext extends FacesContext {
		protected static void setFacesContextAsCurrentInstance(
				FacesContext facesContext) {
			FacesContext.setCurrentInstance(facesContext);
		}
	}

	protected Object getManagedBean(String beanName, FacesContext facesContext) {
		if (facesContext != null && getApplication(facesContext) != null)
			return getApplication(facesContext).getVariableResolver()
				.resolveVariable(facesContext, beanName);
		else
			return null;
	}

	protected Application getApplication(FacesContext facesContext) {
		return facesContext.getApplication();
	}

}